"""
超时管理模块
负责智能计算和管理API请求超时时间
"""

import logging
from typing import Dict, Any

logger = logging.getLogger(__name__)


class TimeoutManager:
    """超时管理器"""

    def __init__(self, settings):
        self.settings = settings

        # 普通模型超时配置
        self.base_timeout_small = getattr(settings, 'base_timeout_small', 360)
        self.base_timeout_medium = getattr(
            settings, 'base_timeout_medium', 480)
        self.base_timeout_large = getattr(settings, 'base_timeout_large', 600)
        self.base_timeout_xlarge = getattr(
            settings, 'base_timeout_xlarge', 720)
        self.base_timeout_xxlarge = getattr(
            settings, 'base_timeout_xxlarge', 900)
        self.max_timeout_limit = getattr(settings, 'max_timeout_limit', 1800)
        self.retry_timeout_multiplier = getattr(
            settings, 'retry_timeout_multiplier', 1.5)

        # 推理模型专用超时配置
        self.reasoning_model_base_timeout_small = getattr(
            settings, 'reasoning_model_base_timeout_small', 300)
        self.reasoning_model_base_timeout_medium = getattr(
            settings, 'reasoning_model_base_timeout_medium', 450)
        self.reasoning_model_base_timeout_large = getattr(
            settings, 'reasoning_model_base_timeout_large', 600)
        self.reasoning_model_base_timeout_xlarge = getattr(
            settings, 'reasoning_model_base_timeout_xlarge', 900)
        self.reasoning_model_base_timeout_xxlarge = getattr(
            settings, 'reasoning_model_base_timeout_xxlarge', 1200)
        self.reasoning_model_max_timeout_limit = getattr(
            settings, 'reasoning_model_max_timeout_limit', 1800)

        # 智能超时开关
        self.smart_timeout_enabled = getattr(
            settings, 'smart_timeout_enabled', True)

    def calculate_smart_timeout(self, requirement_length: int, attempt: int = 0) -> int:
        """智能计算超时时间"""
        if not self.smart_timeout_enabled:
            return 300  # 默认5分钟

        # 根据需求长度确定基础超时时间
        if requirement_length <= 500:
            base_timeout = self.base_timeout_small
            complexity = "小"
        elif requirement_length <= 1500:
            base_timeout = self.base_timeout_medium
            complexity = "中"
        elif requirement_length <= 3000:
            base_timeout = self.base_timeout_large
            complexity = "大"
        elif requirement_length <= 6000:
            base_timeout = self.base_timeout_xlarge
            complexity = "超大"
        else:
            base_timeout = self.base_timeout_xxlarge
            complexity = "极大"

        # 根据重试次数调整超时时间
        timeout = int(
            base_timeout * (self.retry_timeout_multiplier ** attempt))

        # 限制最大超时时间
        timeout = min(timeout, self.max_timeout_limit)

        logger.info(f"需求复杂度: {complexity} ({requirement_length}字符), "
                    f"尝试次数: {attempt+1}, 超时时间: {timeout}秒")

        return timeout

    def calculate_reasoning_model_timeout(self, requirement_length: int, attempt: int = 0) -> int:
        """为推理模型智能计算超时时间（更长的超时时间）"""
        if not self.smart_timeout_enabled:
            return 600  # 默认10分钟

        # 根据需求长度确定基础超时时间（推理模型专用）
        if requirement_length <= 500:
            base_timeout = self.reasoning_model_base_timeout_small
            complexity = "小"
        elif requirement_length <= 1500:
            base_timeout = self.reasoning_model_base_timeout_medium
            complexity = "中"
        elif requirement_length <= 3000:
            base_timeout = self.reasoning_model_base_timeout_large
            complexity = "大"
        elif requirement_length <= 6000:
            base_timeout = self.reasoning_model_base_timeout_xlarge
            complexity = "超大"
        else:
            base_timeout = self.reasoning_model_base_timeout_xxlarge
            complexity = "极大"

        # 根据重试次数调整超时时间
        timeout = int(
            base_timeout * (self.retry_timeout_multiplier ** attempt))

        # 限制最大超时时间（推理模型专用）
        timeout = min(timeout, self.reasoning_model_max_timeout_limit)

        logger.info(f"推理模型超时计算 - 需求复杂度: {complexity} ({requirement_length}字符), "
                    f"尝试次数: {attempt+1}, 超时时间: {timeout}秒")

        return timeout

    def calculate_max_tokens(self, requirement_length: int) -> int:
        """根据需求复杂度动态调整max_tokens"""
        if requirement_length <= 500:
            return 1500
        elif requirement_length <= 1500:
            return 2500
        elif requirement_length <= 3000:
            return 3500
        elif requirement_length <= 6000:
            return 4000
        else:
            return 4000  # 最大值

    def estimate_batch_time(self, modules: list) -> float:
        """估算批量处理时间"""
        total_chars = sum(len(module.get('content', '')) for module in modules)

        # 基于经验的时间估算（分钟）
        if total_chars <= 2000:
            return len(modules) * 1.5  # 每个模块1.5分钟
        elif total_chars <= 5000:
            return len(modules) * 2.5  # 每个模块2.5分钟
        elif total_chars <= 10000:
            return len(modules) * 4.0  # 每个模块4分钟
        else:
            return len(modules) * 6.0  # 每个模块6分钟

    def get_timeout_config(self) -> Dict[str, Any]:
        """获取超时配置信息"""
        return {
            "smart_timeout_enabled": self.smart_timeout_enabled,
            "base_timeout_small": self.base_timeout_small,
            "base_timeout_medium": self.base_timeout_medium,
            "base_timeout_large": self.base_timeout_large,
            "base_timeout_xlarge": self.base_timeout_xlarge,
            "base_timeout_xxlarge": self.base_timeout_xxlarge,
            "max_timeout_limit": self.max_timeout_limit,
            "retry_timeout_multiplier": self.retry_timeout_multiplier
        }

    def adjust_timeout_for_model(self, base_timeout: int, provider: str) -> int:
        """根据模型提供商调整超时时间"""
        # 不同提供商的响应速度可能不同
        multipliers = {
            "openai": 1.0,
            "deepseek": 1.2,  # DeepSeek可能稍慢
            "doubao": 1.3,    # 豆包可能较慢
            "claude": 1.1,    # Claude稍慢
            "gemini": 1.2,    # Gemini稍慢
            "zhipu": 1.3,     # 智谱AI可能较慢
            "local": 0.8      # 本地模型通常更快
        }

        multiplier = multipliers.get(provider.lower(), 1.0)
        adjusted_timeout = int(base_timeout * multiplier)

        # 确保不超过最大限制
        return min(adjusted_timeout, self.max_timeout_limit)

    def should_retry(self, attempt: int, max_retries: int, error_type: str) -> bool:
        """判断是否应该重试"""
        if attempt >= max_retries:
            return False

        # 根据错误类型决定是否重试
        retryable_errors = [
            "timeout",
            "connection",
            "network",
            "rate_limit",
            "server_error"
        ]

        return any(error in error_type.lower() for error in retryable_errors)

    def get_retry_delay(self, attempt: int) -> float:
        """获取重试延迟时间（秒）"""
        # 指数退避策略
        base_delay = 2.0
        max_delay = 30.0

        delay = min(base_delay * (2 ** attempt), max_delay)
        return delay

    def log_timeout_info(self, requirement_length: int, timeout: int, attempt: int):
        """记录超时信息"""
        logger.info(
            f"超时配置 - 需求长度: {requirement_length}, "
            f"超时时间: {timeout}s, 尝试次数: {attempt+1}, "
            f"智能超时: {'启用' if self.smart_timeout_enabled else '禁用'}"
        )
